import { _decorator, CCInteger, Component, EventTouch, Node, UITransform, Vec2, Vec3 } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('Joystick')
export class Joystick extends Component {

    @property(Node)
    background: Node = null

    @property(Node)
    rocker: Node = null

    @property(CCInteger)
    radius: number = 100


    private _touchDirection: Vec3 = Vec3.ZERO
    private startPoint: Vec3 = null
    private _isTouchMove: boolean = false

    protected onLoad(): void {
        this.reset()
        this.node.on(Node.EventType.TOUCH_START, this.touchStart, this)
        this.node.on(Node.EventType.TOUCH_MOVE, this.touchMove, this)
        this.node.on(Node.EventType.TOUCH_CANCEL, this.touchCancel, this)
        this.node.on(Node.EventType.TOUCH_END, this.touchEnd, this)
    }

    private touchStart(et: EventTouch) {
        this._isTouchMove = false
        this.show()
        this.startPoint = et.getUILocation().toVec3()
        this.background.setWorldPosition(this.startPoint)
    }

    private touchMove(et: EventTouch) {
        const movePoint = et.getUILocation().toVec3()
        const moveDirction = movePoint.clone().subtract(this.startPoint)
        const moveNormalize = moveDirction.clone().normalize()
        
        let toPosition = movePoint
        if (moveDirction.length() > this.radius) {
            toPosition = moveNormalize.clone().multiplyScalar(this.radius)
            toPosition = this.background.getComponent(UITransform).convertToWorldSpaceAR(toPosition)
        }
        this.rocker.setWorldPosition(toPosition)
        this._touchDirection = moveNormalize
        this._isTouchMove = true
    }

    private touchCancel(et: EventTouch) {
        this.reset()
    }

    private touchEnd(et: EventTouch) {
        this.reset()
    }

    private hide() {
        this.background.active = false;
        this.rocker.active = false;
    }

    private show() {
        this.background.active = true;
        this.rocker.active = true;
    }

    private reset() {
        this.hide()
        this.rocker.setPosition(Vec3.ZERO)
        this._touchDirection = Vec3.ZERO;
        this._isTouchMove = false
    }

    private vec2ToAngle(dir: Vec2): number {
        //弧度值
        let radian = Math.atan2(dir.y, dir.x);
        //弧度转角度
        return radian * (180 / Math.PI);
    }
    /**
     * 摇杆旋转角度
     * @returns 
     */
    public getAngle(): number {
        return this.vec2ToAngle(this._touchDirection.toVec2())
    }

    /**
     * 摇杆移动方向
     */
    public getDirection(): Vec3 {
        return this._touchDirection.clone();
    }

    /**
     * 摇杆是否移动
     * @returns 
     */
    public isMove(): boolean {
        return this._isTouchMove
    }
}